<?php

namespace App\Models\Trip\OrderPay\Repositories;

use App\Models\Plane\PlaneOrders\PlaneOrder;
use App\Models\Plane\PlaneOrders\Repositories\Interfaces\PlaneOrderRepositoryInterface;
use App\Models\Train\TrainOrders\Repositories\Interfaces\TrainOrdersRepositoryInterface;
use App\Models\Train\TrainOrders\TrainOrder;
use App\Models\Trip\OrderPay\OrderPay;
use App\Models\Trip\OrderPay\OrderPayDetail;
use App\Models\Trip\OrderPay\Repositories\Interfaces\OrderPayDetailsRepositoryInterface;
use App\Trip\Orders\TripType;
use App\Trip\Repository\BaseRepository;
use Exception;
use Illuminate\Support\Facades\Validator;

class OrderPayDetailsRepository extends BaseRepository implements OrderPayDetailsRepositoryInterface
{

    public function __construct(OrderPayDetail $model)
    {
        parent::__construct($model);
    }


    /**
     * @throws Exception
     */
    public function addMore(OrderPay $pay, array $data)
    {
        $validator = Validator::make($data, [
            '*.user_id'       => "required",
            '*.trip_id'       => "required",
            '*.trip_type'     => "required",
            '*.pay_sn'        => "required",
            '*.order_sn'      => "required",
            '*.order_amount'  => "required",
            '*.order_info'    => "required",
            '*.business_type' => "required",
        ]);
        if ($validator->fails()) {
            throw new Exception("param error");
        }

        $trainOrderRepo = app(TrainOrdersRepositoryInterface::class);
        $planeOrderRepo = app(PlaneOrderRepositoryInterface::class);
        foreach ($data as $detail_data) {
            $order_info = $detail_data['order_info'];
            if ($order_info instanceof TrainOrder) {
                $detail = $this->getTrainOrderPayDetail($order_info, $detail_data['business_type']);
            } elseif ($order_info instanceof PlaneOrder) {
                $detail = $this->getPlaneOrderPayDetail($order_info, $detail_data['business_type']);
            } else {
                throw new Exception("trip_type error");
            }

            if (!$detail) {
                $detail = $this->create($detail_data);
            } else {
                if ($detail->getRealAmount() != $detail_data['order_amount']) {
                    $detail->update([
                        'order_amount' => $detail_data['order_amount'],
                    ]);
                }
            }
            if (!$detail instanceof OrderPayDetail) {
                throw new Exception("支付明细创建失败，请重试");
            }

            if ($order_info instanceof TrainOrder) {
                $trainOrderRepo->saveOrderPaySn($order_info, $detail->getPaySn());
            } elseif ($order_info instanceof PlaneOrder) {
                $planeOrderRepo->saveOrderPaySn($order_info, $detail->getPaySn());
            } else {
                throw new Exception("酒店等其他支付暂时未实现");
            }
        }
        return true;
    }

    /**
     * 获取火车订单 支付详情,下单,改签,抢票
     *
     * @param TrainOrder $order
     * @param int        $business_type
     *
     * @return OrderPayDetail|null
     */
    public function getTrainOrderPayDetail(TrainOrder $order, int $business_type): ?OrderPayDetail
    {
        return $this->findOneBy(
            [
                'order_sn'      => $order->getOrderSn(),
                'separate'      => 0,
                'business_type' => $business_type,
                'trip_type'     => TripType::TRIP_TYPE_TRAIN,
            ]
        );

    }

    /**
     * 获取飞机支付业务详情
     * @param PlaneOrder $order
     * @param int        $business_type
     * @return OrderPayDetail|null
     */
    public function getPlaneOrderPayDetail(PlaneOrder $order, int $business_type): ?OrderPayDetail
    {
        return $this->findOneBy(
            [
                'order_sn'      => $order->getOrderSn(),
                'separate'      => 0,
                'business_type' => $business_type,
                'trip_type'     => TripType::TRIP_TYPE_PLANE,
            ]
        );
    }

    public function findByPaySn(string $pay_sn)
    {
        return $this->findBy([
            'pay_sn' => $pay_sn,
        ]);
    }
}